#!/usr/bin/env python
"""Framework for getting filetype-specific metadata.

Instantiate appropriate class with filename.  Returned object acts like a
dictionary, with key-value pairs for each piece of metadata.
    import fileinfo
    info = fileinfo.MP3FileInfo("/music/ap/mahadeva.mp3")
    print "\\n".join(["%s=%s" % (k, v) for k, v in info.items()])

Or use listDirectory function to get info on all files in a directory.
    for info in fileinfo.listDirectory("/music/ap/", [".mp3"]):
            ...

Framework can be extended by adding classes for particular file types, e.g.
HTMLFileInfo, MPGFileInfo, DOCFileInfo.  Each class is completely responsible for
parsing its files appropriately; see MP3FileInfo for example.
"""
import os
import sys
from UserDict import UserDict

def stripnulls(data):
    "strip file metadata"
    if isinstance(data, unicode):
        return data.replace("\00", "").sctrip()
    else:
        return data.replace("\00", "").strip().decode('gb2312').encode('utf-8')

class FileInfo(UserDict):
    "store file metatda"
    def __init__(self, filename=None):
        UserDict.__init__(self)
        self["name"] = filename


class MP3FileInfo(FileInfo):
    "store ID3v1.0 Mp3 tags"

    tagDataMap = {
            "title"  : (3, 33, stripnulls),
            "artist" : (33, 63, stripnulls),
            "album"  : (63, 93, stripnulls),
            "year"   : (93, 97, stripnulls),
            "comment": (97, 126, stripnulls),
            "genre"  : (127,128,ord) }
    def __parse(self, filename):
        self.clear()
        try:
            fsock = open(filename,"rb",0)
            try:
                fsock.seek(-128,2)
                tagdata = fsock.read(128)
            finally:
                fsock.close()
            if tagdata[:3] == "TAG":
                for tag, (start, end, parseFunc) in self.tagDataMap.items():
                    self[tag] = parseFunc(tagdata[start:end])
        except IOError:
            print("exception")
            pass

    def __setitem__(self, key, item):
        if key == "name" and item:
            self.__parse(item)
        FileInfo.__setitem__(self, key ,item)



def listDirectory(directory, fileExtlist):
    fileList = [os.path.normcase(f) for f in os.listdir(directory)]
    fileList = [os.path.join(directory, f)
            for f in fileList 
            if os.path.splitext(f)[1] in fileExtlist ]

    def getFileInfoClass(filename, module=sys.modules[FileInfo.__module__]):
        subclass = "%sFileInfo" % os.path.splitext(filename)[1].upper()[1:]
        return hasattr(module, subclass) and getattr(module, subclass) or FileInfo

    return [getFileInfoClass(f)(f) for f in fileList]



if __name__ == "__main__":
    for info in listDirectory("/root/xianzi/", [".mp3"]):
        print("\n".join(["%s=%s" % (k,v) for k,v in info.items()]))

